package com.zendaimoney.test.simulation.utils;

import com.google.common.collect.Lists;
import com.zendaimoney.test.simulation.action.BaseAction;
import com.zendaimoney.test.simulation.annotation.RequestCategory;
import com.zendaimoney.test.simulation.enums.ThirdType;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
@Component
@Lazy(false)
public class SpringContextHelper implements ApplicationContextAware {

    private static Map<String, BaseAction> targetMap = new HashMap<String, BaseAction>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 加载所有action
        List<Class<? extends BaseAction>> list = findReqActionClass();
        for (Class<? extends BaseAction> clazz : list) {
            RequestCategory annotation = clazz.getAnnotation(RequestCategory.class);
            if (annotation == null) {
                continue;
            }
            //业务类型
            String bizType = annotation.bizType();
            //第三方通道编码
            ThirdType thirdType = annotation.thirdType();

            BaseAction action = (BaseAction) applicationContext.getBean(clazz.getName());

            addTargetMap(targetMap, thirdType.getCode() + "_" + bizType, action);
        }
    }

    /**
     * 获取处理业务逻辑的类
     *
     * @param thirdType
     * @param bizType
     * @return
     */
    public BaseAction getTargetAction(String thirdType, String bizType) {
        BaseAction action = targetMap.get(thirdType + "_" + bizType);
        if(action==null) {
            throw new RuntimeException("要查找的service处理类不存在,请查看相关请求数据;");
        }
        return action;
    }

    private void addTargetMap(Map<String, BaseAction> targetMap, String key, BaseAction target) {
        if (targetMap.get(key) != null) {
            throw new RuntimeException("Map中将要添加的key对应的action已经存在,异常: " + key + " class : " + target.getClass().getName());
        }
        targetMap.put(key, target);
    }

    /**
     * 扫描classPath下的component
     * @return
     */
    @SneakyThrows
    private List<Class<? extends BaseAction>> findReqActionClass() {
        List<Class<? extends BaseAction>> list = Lists.newArrayList();
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AnnotationTypeFilter(RequestCategory.class));
        Set<BeanDefinition> beanDefinitions = provider.findCandidateComponents("com.zendaimoney.test.simulation.action");
        for (BeanDefinition beanDefinition : beanDefinitions) {
            Class<? extends BaseAction> clazz = (Class<? extends BaseAction>)Class.forName(beanDefinition.getBeanClassName());
            list.add(clazz);
        }

        return list;
    }
}
